package com.best.core.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.best.core.entity.CommonResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.internal.Nullable;

import lombok.extern.slf4j.Slf4j;

/**
 * json工具类
 */
@Slf4j
public class JsonUtils {

    public static final ObjectMapper mapper = new ObjectMapper();

    /**
     * @description: 对象转json字符串
     * @Param: [obj]
     * @return: java.lang.String
     * @author: 李东
     * @time: 2020-7-6 11:27
     **/
    @Nullable
    public static String serialize(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj.getClass() == String.class) {
            return (String) obj;
        }
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象转json字符串出错：{}", e);
            throw new RuntimeException("对象转json字符串出错", e);
        }
    }

    /**
     * @description: json字符串转对象
     * @Param: [json, tClass]
     * @return: T
     * @author: 李东
     * @time: 2020-7-6 11:30
     **/
    @Nullable
    public static <T> T parse(String json, Class<T> tClass) {
        try {
            return mapper.readValue(json, tClass);
        } catch (IOException e) {
            log.error("json字符串转对象出错：{}", e);
            throw new RuntimeException("json字符串转对象出错", e);
        }
    }

    /**
     * @description: json字符串转对象的List集合
     * @Param: [json, eClass]
     * @return: java.util.List<E>
     * @author: 李东
     * @time: 2020-7-6 11:31
     **/
    @Nullable
    public static <E> List<E> parseList(String json, Class<E> eClass) {
        try {
            return mapper.readValue(json,
                    mapper.getTypeFactory().constructCollectionType(List.class, eClass));
        } catch (IOException e) {
            log.error("json字符串转对象的List集合出错：{}", e);
            throw new RuntimeException("json字符串转对象的List集合出错", e);
        }
    }

    /**
     * @description: json字符串对象对应的map集合
     * @Param: [json, kClass, vClass]
     * @return: java.util.Map<K,V>
     * @author: 李东
     * @time: 2020-7-6 11:32
     **/
    @Nullable
    public static <K, V> Map<K, V> parseMap(String json, Class<K> kClass, Class<V> vClass) {
        try {
            return mapper.readValue(json,
                    mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
        } catch (IOException e) {
            log.error("json字符串对象对应的map集合出错：{}", e);
            throw new RuntimeException("json字符串对象对应的map集合出错", e);
        }
    }


    /**
     * 根据类型，将json字符串转对应类型的对象或集合
     *
     * @param json
     * @param type
     * @param <T>
     * @return
     */
    @Nullable
    public static <T> T parseByType(String json, TypeReference<T> type) {
        try {
            return mapper.readValue(json, type);
        } catch (IOException e) {
            log.error("根据对象类型，将json字符串转对象出错：{}", e);
            throw new RuntimeException("根据对象类型，将json字符串转对象出错", e);
        }
    }


    /**
     * @description: 具体使用示例 main方法测试
     * @Param: [args]
     * @return: void
     * @author: 李东
     * @time: 2020-7-6 11:46
     **/
    public static void main(String[] args) {
        // 1.对象转json
        CommonResult res = new CommonResult();
        res.setCode(200);
        res.setMsg("success");
        res.setFlag(true);
        String jsonObj = JsonUtils.serialize(res);
        System.out.println("对象转json:" + jsonObj);

        // 2.List集合转json
        List<String> list = new ArrayList<>();
        list.add("123");
        list.add("234");
        list.add("345");
        String jsonList = JsonUtils.serialize(list);
        System.out.println("集合转json:" + jsonList);

        // 3.map集合转json
        Map<String, String> map = new HashMap<>();
        map.put("key1", "123");
        map.put("key2", "234");
        map.put("key3", "345");
        String jsonMap = JsonUtils.serialize(map);
        System.out.println("map集合转json:" + jsonMap);

        // 4.json字符串转对象
        CommonResult parse = JsonUtils.parse(jsonObj, CommonResult.class);
        System.out.println("json字符串转对象:" + parse);

        // 5.json字符串转List集合
        List<String> listStr = JsonUtils.parseList(jsonList, String.class);
        System.out.println("json字符串转List集合" + list);

        // 6.json字符串转Map集合
        Map<String, String> mapStr = JsonUtils.parseMap(jsonMap, String.class, String.class);
        System.out.println("json字符串转Map集合:" + mapStr);

        // 7.根据类型，将json字符串转对应类型的对象或集合
        List<String> listType =
                JsonUtils.parseByType(jsonList, new TypeReference<List<String>>() {});
        System.out.println("根据类型，将json字符串转对应类型的对象或集合list:" + listType);
        Map<String, String> mapType =
                JsonUtils.parseByType(jsonMap, new TypeReference<Map<String, String>>() {});
        System.out.println("根据类型，将json字符串转对应类型的对象或集合map:" + mapType);

    }

}
